
package com.example.blog.auth;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.example.blog.base.CurrentAccount;
import com.example.blog.base.Result;
import com.example.blog.exception.CommonErrorCode;
import com.example.blog.util.CurrentUserUtils;
import com.example.blog.util.RedisCacheUtil;
import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;

/**
 * @Classname AuthFilter
 * @Description TODO
 * @Version 1.0.0
 * @Date 2023/11/19 12:36
 * @Created by wlh12
 */
@WebFilter(urlPatterns = "/**")
@Component
public class AuthFilter implements Filter {

    @Autowired
    private RedisCacheUtil redisCacheUtil;

    /**
     * 白名单
     */
    private final String[] WHITE_LIST = {
            "/blog/sysUser/login",
            "/blog/sysUser/register",
            "/blog/article/search",
            "/blog/article/view/*",
            "/blog/article/list",
            "/blog/sysUser/getInfo/*",
            "/blog/favorites_folders/public-list",
            "/blog/dictionaryGroup/list",
            "/blog/dictionaryItem/list/*",
            "/blog/comment/page-list",
            "/blog/reply/page-list",
            "/blog/sysUser/search"
    };

    private final AntPathMatcher matcher = new AntPathMatcher();

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
        String uri = httpServletRequest.getRequestURI();
        boolean match = Arrays.stream(WHITE_LIST).anyMatch(i -> matcher.match(i,uri));
        String authorization = httpServletRequest.getHeader("Authorization");
        if (StrUtil.isBlank(authorization)) {
            if (!match) {
                error(CommonErrorCode.LOGIN,httpServletResponse);
                return;
            }
        }
        Object token = redisCacheUtil.get(authorization);
        if (token != null) {
            CurrentAccount currentAccount = JSONUtil.toBean(JSONUtil.toJsonStr(token), CurrentAccount.class);
            CurrentUserUtils.setThreadLocal(currentAccount);
        } else {
            CurrentUserUtils.setThreadLocal(null);
        }
        filterChain.doFilter(servletRequest,servletResponse);
    }

    private void error(CommonErrorCode errorCode, HttpServletResponse response) {
        Result<Void> result = new Result<>();
        result.setCode(errorCode.getCode());
        result.setMessage(errorCode.getMessage());
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json;charset=UTF-8");
        try (PrintWriter writer = response.getWriter()) {
            writer.write(JSONUtil.toJsonStr(result));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

}
